package com.oig.sys.msg.app.impl;

import com.oig.common.exception.BadRequestException;
import com.oig.sys.msg.app.IAppNoticeMsgService;
import com.oig.sys.msg.auth.IDepUserService;
import com.oig.sys.msg.constants.MsgEnums;
import com.oig.sys.msg.dto.NoticeMsgDto;
import com.oig.sys.msg.file.IDepFileService;
import com.oig.sys.msg.im.handler.HandlerHolder;
import com.oig.sys.msg.service.ITbNoticeMsgReceiverService;
import com.oig.sys.msg.service.ITbNoticeMsgService;
import com.oig.sys.msg.service.ITbPushChannelService;
import com.oig.sys.msg.vo.NoticeMsgFileVo;
import com.oig.sys.msg.vo.NoticeMsgReceiverVo;
import com.oig.sys.msg.vo.NoticeMsgVo;
import com.oig.sys.msg.vo.PushChannelVo;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
@RequiredArgsConstructor
public class AppNoticeMsgServiceImpl implements IAppNoticeMsgService {

    private final ITbNoticeMsgService noticeMsgService;
    private final ITbNoticeMsgReceiverService noticeMsgReceiverService;
    private final ITbPushChannelService pushChannelService;

    private final IDepFileService depFileService;
    private final IDepUserService depUserService;
    private final HandlerHolder handlerHolder;


    private void checkReceiver(NoticeMsgDto noticeMsgDto){
        if (MsgEnums.MsgType.TARGET.getCode().equals(noticeMsgDto.getMsgType())){
            if (StringUtils.isBlank(noticeMsgDto.getReceiverType())){
                throw new BadRequestException("定向消息必须指定接收方");
            }
            if (MsgEnums.ReceiverType.TENANT.getCode().equals(noticeMsgDto.getReceiverType())
                    ||MsgEnums.ReceiverType.DEPT.getCode().equals(noticeMsgDto.getReceiverType())){
                if (noticeMsgDto.getReceiverId()==null || StringUtils.isBlank(noticeMsgDto.getReceiverName())){
                    throw new BadRequestException("收消息方必填")	;
                }
            } else if (MsgEnums.ReceiverType.USER.getCode().equals(noticeMsgDto.getReceiverType())){
                if (noticeMsgDto.getNoticeMsgReceiverList()==null||noticeMsgDto.getNoticeMsgReceiverList().isEmpty()){
                    throw new BadRequestException("收消息方必填")	;
                }
            }
        }
    }


    @GlobalTransactional
    @Override
    public NoticeMsgVo addNoticeMsg(NoticeMsgDto noticeMsgDto) {
        this.checkReceiver(noticeMsgDto);
        noticeMsgDto.setNoticeMsgReceiverList(this.depUserService.changeOrBuildReceiver(noticeMsgDto));
        NoticeMsgVo noticeMsgVo = this.noticeMsgService.addNoticeMsg(noticeMsgDto);
        List<NoticeMsgFileVo> msgFileVoList = depFileService.addOrUpdateAllFiles(noticeMsgVo, noticeMsgDto.getNoticeMsgFileDtoList());
        noticeMsgVo.setNoticeMsgFileVoList(msgFileVoList);
        return noticeMsgVo;
    }

    @GlobalTransactional
    @Override
    public NoticeMsgVo updateNoticeMsg(NoticeMsgDto noticeMsgDto) {
        this.checkReceiver(noticeMsgDto);
        noticeMsgDto.setNoticeMsgReceiverList(this.depUserService.changeOrBuildReceiver(noticeMsgDto));
        NoticeMsgVo noticeMsgVo = this.noticeMsgService.updateNoticeMsg(noticeMsgDto);
        List<NoticeMsgFileVo> msgFileVoList = this.depFileService.addOrUpdateAllFiles(noticeMsgVo, noticeMsgDto.getNoticeMsgFileDtoList());
        noticeMsgVo.setNoticeMsgFileVoList(msgFileVoList);
        return noticeMsgVo;
    }

    @Override
    public NoticeMsgVo auditNoticeMsg(NoticeMsgDto noticeMsgDto) {
        return this.noticeMsgService.auditNoticeMsg(noticeMsgDto);
    }

    @GlobalTransactional
    @Override
    public void delNoticeMsg(Integer id) {
        this.noticeMsgService.delNoticeMsg(id);
        this.depFileService.delAllNoticeFiles(id);
    }

    @Override
    public NoticeMsgVo getNoticeMsgMainInfo(Integer id) {
        return this.noticeMsgService.getNoticeMsgMainInfo(id);
    }

    @Override
    public NoticeMsgVo getNoticeMsg(Integer id) {
        return this.noticeMsgService.getNoticeMsg(id);
    }

    @Override
    public NoticeMsgVo addSysNoticeMsg(NoticeMsgDto noticeMsgDto) {
        this.checkReceiver(noticeMsgDto);
        noticeMsgDto.setNoticeMsgReceiverList(this.depUserService.changeOrBuildReceiver(noticeMsgDto));
        return this.noticeMsgService.addSysNoticeMsg(noticeMsgDto);
    }


    @Override
    public NoticeMsgVo publishMsg(NoticeMsgDto noticeMsgDto) {
        return this.noticeMsgService.publishMsg(noticeMsgDto);
    }

    @Override
    public List<NoticeMsgVo> findUnSendMsg() {
        return this.noticeMsgService.findUnSendMsg();
    }

    @Override
    public void pushMsg(NoticeMsgVo noticeMsgVo) {
        //站内通知公告可以不用 企微或飞书等im软件 或短信，邮件等通知
        if (noticeMsgVo.getPushChannelId()==null){
            log.debug("inner msg pushed");
            noticeMsgService.updateMsgStatusById(noticeMsgVo.getId());
            return;
        }
        //有通知渠道的。
        // 手机号
        if (MsgEnums.MsgType.TARGET.getCode().equals(noticeMsgVo.getMsgType())) {
            log.debug(" push query mobiles");
            List<NoticeMsgReceiverVo> noticeMsgReceiverVoList = noticeMsgReceiverService.findMsgReceiver(noticeMsgVo.getId());
            List<Integer> receiverIdList = noticeMsgReceiverVoList.stream().map(NoticeMsgReceiverVo::getReceiverId).collect(Collectors.toList());
            List<String> userMobiles = this.depUserService.findUserMobileByUserIds(receiverIdList);
            log.debug(" push query mobiles result : {}", userMobiles);
            noticeMsgVo.setMobiles(userMobiles);
        }
        // 渠道 先不做缓存了
        PushChannelVo pushChannel = this.pushChannelService.getPushChannel(noticeMsgVo.getPushChannelId());
        if (pushChannel==null){
            log.error("channel error..");
            return;
        }
        //  PushChannelVo pushChannel = pushChannelService.getPushChannel(noticeMsgVo.getPushChannelId());
        noticeMsgVo.setChannelConfig(pushChannel.getChannelConfig());
        log.debug(" channel config : {}", pushChannel.getChannelConfig());
        boolean isSuccess = handlerHolder.route(pushChannel.getChannelType() + noticeMsgVo.getMsgType()).handler(noticeMsgVo);
        if (isSuccess) {
            log.debug(" pushed success ");
            noticeMsgService.updateMsgStatusById(noticeMsgVo.getId());
        } else {
            log.warn("pushed fail..");
            //加个推送次数，否则一直推也不好。
            noticeMsgService.updateMsgSendTimes(noticeMsgVo.getId());
        }
    }

}
